﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.IO;
using System.Diagnostics;
using System.Windows.Forms;

namespace PRO_DOCS.DocumentManagementSystem.Petrolium.WIN._7z
{
    public static class Zipping
    {
        public enum CompressionLevel
        {
            Default,
            [Description("-mx0")]
            Store,
            [Description("-mx1")]
            Fastest,
            [Description("-mx3")]
            Fast,
            [Description("-mx5")]
            Normal,
            [Description("-mx7")]
            Maximum,
            [Description("-mx9")]
            Ultra
        }

        public enum CompressionType
        {
            Default,
            [Description("-t7z")]
            SevenZ,
            [Description("-tgzip")]
            GZip,
            [Description("-tzip")]
            Zip,
            [Description("-tbzip2")]
            BZip2,
            [Description("-ttar")]
            Tar,
            [Description("-tiso")]
            Iso,
            [Description("-tudf")]
            Udf
        }

        public static string Compress(string zPath, string folderSourcePath, string fileDestination, bool isOverwrite = false, string pass = null, int splitSizeInKb = 0, CompressionLevel compressionLevel = CompressionLevel.Default, CompressionType compressionType = CompressionType.Default, bool isSolid = true, int countOfThreads = 0)
        {
            try
            {
                #region Validate

                if (!File.Exists(zPath))
                {
                    return "7z exe file not found";
                }
                if (!Directory.Exists(folderSourcePath))
                {
                    return "working folder not found";
                }
                if (File.Exists(fileDestination))
                {
                    return "destination file name already exist";
                }

                #endregion
                //Enumerations.GetEnumDescription((MyEnum)value);
                var args = string.Empty;
                args = string.Format("{0} \"{1}\" \"{2}\"", "a", fileDestination, folderSourcePath);
                var procRes = string.Empty;

                if (pass != null)
                    args += " -mhe -p" + pass;
                if (compressionLevel != CompressionLevel.Default)
                {
                    switch (compressionLevel)
                    {
                        case CompressionLevel.Store:
                            args += " -mx0";
                            break;
                        case CompressionLevel.Fastest:
                            args += " -mx1";
                            break;
                        case CompressionLevel.Fast:
                            args += " -mx3";
                            break;
                        case CompressionLevel.Normal:
                            args += " -mx5";
                            break;
                        case CompressionLevel.Maximum:
                            args += " -mx7";
                            break;
                        case CompressionLevel.Ultra:
                            args += " -mx9";
                            break;
                        default:
                            throw new ArgumentOutOfRangeException("compressionLevel");
                    }
                }

                if (compressionType != CompressionType.Default)
                {
                    switch (compressionType)
                    {
                        case CompressionType.SevenZ:
                            args += " t7z";
                            break;
                        case CompressionType.GZip:
                            args += " -tgzip";
                            break;
                        case CompressionType.Zip:
                            args += " -tzip";
                            break;
                        case CompressionType.BZip2:
                            args += " -tbzip2";
                            break;
                        case CompressionType.Tar:
                            args += " -ttar";
                            break;
                        case CompressionType.Iso:
                            args += " -tiso";
                            break;
                        case CompressionType.Udf:
                            args += " -tudf";
                            break;
                        default:
                            throw new ArgumentOutOfRangeException("compressionType");
                    }
                }

                if (isSolid)
                    args += " -ms=on";
                else
                    args += " -ms=off";

                if (isOverwrite)
                    args += " -aoa";

                if (splitSizeInKb != 0)
                    args += " -v" + splitSizeInKb + "k";

                if (countOfThreads > 0)
                    args += " -mmt=" + countOfThreads;

                var zProcInf = new ProcessStartInfo("\"" + zPath + "\"", args);
                zProcInf.CreateNoWindow = true;
                zProcInf.WindowStyle = ProcessWindowStyle.Hidden;
                var proc = Process.Start(zProcInf);
                proc.WaitForExit();
                switch (proc.ExitCode)
                {
                    case 0:
                        return "No error";
                    case 1:
                        return
                            "Warning (Non fatal error(s)) , one or more files were locked by some other application, so they were not compressed. ";
                    case 2:
                        return "Fatal error";
                    case 7:
                        return "Command line error";
                    case 8:
                        return "Not enough memory for operation";
                    case 255:
                        return "User stopped the process";
                }
                return "";
            }
            catch (Exception ex)
            {
                Back.Backup.WriteToEventLog(ex.ToString());
                return ex.ToString();
            }
        }

        public static string Compress(string zPath, string folderSourcePath, string fileDestination, string command)
        {
            try
            {
                string args = string.Format("{0} \"{1}\" \"{2}\" {3}", "a", fileDestination, folderSourcePath, command);
                
                var zProcInf = new ProcessStartInfo("\"" + zPath + "\"", args);


                zProcInf.CreateNoWindow = true;
                zProcInf.WindowStyle = ProcessWindowStyle.Hidden;
                var proc = Process.Start(zProcInf);
                proc.WaitForExit();
                switch (proc.ExitCode)
                {
                    case 0:
                        return "No error";
                    case 1:
                        return
                            "Warning (Non fatal error(s)) , one or more files were locked by some other application, so they were not compressed. ";
                    case 2:
                        return "Fatal error";
                    case 7:
                        return "Command line error";
                    case 8:
                        return "Not enough memory for operation";
                    case 255:
                        return "User stopped the process";
                }
                return "";
            }
            catch (Exception ex)
            {
                Back.Backup.WriteToEventLog(ex.ToString());
                System.Windows.Forms.MessageBox.Show(ex.ToString());
                return "";
            }
        }

        public static string Extract(string zPath, string fileSource, string folderDestination, string pass = null, bool isOverwrite = true)
        {
            try
            {
                #region Validate

                if (!File.Exists(zPath))
                {
                    return "7z exe file not found";
                }
                if (Directory.Exists(fileSource))
                {
                    return "file not found";
                }
                if (!File.Exists(folderDestination))
                {
                    return "folder distination not found";
                }

                #endregion

                var args = string.Empty;

                args = string.Format("{0} \"{1}\" -o\"{2}\"", "x", fileSource, folderDestination);
                var procRes = string.Empty;
                if (pass != null)
                    args += " -p" + pass;
                if (isOverwrite)
                    args += " -aoa";//overwrite existing files
                else
                    args += " -aos";//skip existing files

                var zProcInf = new ProcessStartInfo("\"" + zPath + "\"", args);
                zProcInf.CreateNoWindow = true;
                zProcInf.WindowStyle = ProcessWindowStyle.Hidden;
                var proc = Process.Start(zProcInf);
                proc.WaitForExit();
                switch (proc.ExitCode)
                {
                    case 0:
                        return "No error";
                    case 1:
                        return
                            "Warning (Non fatal error(s)) , one or more files were locked by some other application, so they were not compressed. ";
                    case 2:
                        return "Fatal error";
                    case 7:
                        return "Command line error";
                    case 8:
                        return "Not enough memory for operation";
                    case 255:
                        return "User stopped the process";
                }
                return "";
            }
            catch (Exception ex)
            {
                Back.Backup.WriteToEventLog(ex.ToString());
                return ex.ToString();
            }
        }


        public static string ExtractWithCommand(string zPath, string fileSource, string folderDestination, string command)
        {
            try
            {
                #region Validate

                if (!File.Exists(zPath))
                {
                    return "7z exe file not found";
                }
                if (Directory.Exists(fileSource))
                {
                    return "file not found";
                }
                if (!Directory.Exists(folderDestination))
                {
                    return "folder distination not found";
                }

                #endregion

                var args = string.Empty;

                args = string.Format("{0} \"{1}\" -o\"{2}\" {3}", "x", fileSource, folderDestination, command);

                var zProcInf = new ProcessStartInfo("\"" + zPath + "\"", args);
                zProcInf.CreateNoWindow = true;
                zProcInf.WindowStyle = ProcessWindowStyle.Hidden;
                var proc = Process.Start(zProcInf);
                proc.WaitForExit();
                switch (proc.ExitCode)
                {
                    case 0:
                        return "No error";
                    case 1:
                        return
                            "Warning (Non fatal error(s)) , one or more files were locked by some other application, so they were not compressed. ";
                    case 2:
                        return "Fatal error";
                    case 7:
                        return "Command line error";
                    case 8:
                        return "Not enough memory for operation";
                    case 255:
                        return "User stopped the process";
                }
                return "No error";
            }
            catch (Exception ex)
            {
                Back.Backup.WriteToEventLog(ex.ToString());
                return ex.ToString();
            }
        }

    }
}